<?php

namespace app\common\listener;

use think\facade\Db;
use think\facade\Log;

class HandleRiskTag
{
    /**
     * 事件处理方法：当风险标签被应用时触发
     *
     * @param int $userId 用户ID
     * @param string $tagCode 风险标签编码（如 emulator_user）
     * @param array $context 请求上下文（设备、IP等）
     */
    public function handle($userId, $tagCode, $context = [])
    {
        // 1. 从数据库获取标签配置（含 risk_score 和 risk_level）
        $tagConfig = $this->getTagConfig($tagCode);
        if (!$tagConfig) {
            Log::warning("未知风险标签被触发: {$tagCode}");
            return;
        }

        // 2. 写入 cc_risk_records 表（核心风控日志）
        $this->logToRiskRecords($userId, $tagConfig, $context);

        // 3. 根据风险等级执行不同响应动作
        $this->takeAction($userId, $tagConfig, $context);
    }

    /**
     * 写入风控记录表 cc_risk_records
     */
    private function logToRiskRecords($userId, $tagConfig, $context)
    {
        $data = [
            'user_id'         => $userId,
            'ip'              => $context['ip'] ?? '',
            'risk_type'       => $tagConfig['code'],        // 风险类型（标签code）
            'app_version'     => $context['app_version'] ?? null,
            'device_platform' => $context['device_platform'] ?? null,
            'device_type'     => $context['device_type'] ?? null,
            'device_brand'    => $context['device_brand'] ?? null,
            'device_os'       => $context['device_os'] ?? null,
            'latitude'        => $context['latitude'] ?? null,
            'longitude'       => $context['longitude'] ?? null,
            'carrier'         => $context['carrier'] ?? null,
            'risk_score'      => $tagConfig['risk_score'],  // 风险评分（100,90...）
            'risk_tags'       => $tagConfig['code'],        // 标签本身（可扩展为逗号分隔）
            'create_time'     => time(),                    // 时间戳（int）
        ];

        try {
            Db::name('cc_risk_records')->insert($data);
            Log::info('风控记录已写入', ['user_id' => $userId, 'risk_type' => $tagConfig['code']]);
        } catch (\Exception $e) {
            Log::error('写入风控记录失败', [
                'error' => $e->getMessage(),
                'data'  => $data
            ]);
        }
    }

    /**
     * 根据风险等级执行响应动作
     */
    private function takeAction($userId, $tagConfig, $context): void
    {
        $level = $tagConfig['risk_level'];
        $name  = $tagConfig['name'];

        switch ($level) {
            case 'high':
                // 高风险：封禁用户 + 告警
                $this->banUser($userId, "触发高风险行为：{$name}", $context['ip'] ?? '');
                $this->sendAlert("🔴 高风险用户", "用户{$userId} 触发【{$name}】");
                break;

            case 'medium':
                if ($tagConfig['code'] === 'frequent_withdraw') {
                    $this->freezeWithdraw($userId);
                } else {
                    $this->increaseRiskScore($userId, $tagConfig['risk_score']);
                }
                break;

            case 'low':
                $this->increaseRiskScore($userId, $tagConfig['risk_score']);
                break;

            default:
                Log::info("未定义风险响应", ['tag' => $tagConfig['code']]);
        }
    }

    /**
     * 封禁用户
     */
    private function banUser($userId, $reason, $ip)
    {
        Db::name('user')->where('id', $userId)->update(['status' => 0]);
        Db::name('user_ban')->insert([
            'user_id' => $userId,
            'reason' => $reason,
            'ip' => $ip,
            'create_time' => time(),
        ]);
        // 清除会话
        cache("session:{$userId}", null);
    }

    /**
     * 冻结提现功能
     */
    private function freezeWithdraw($userId)
    {
        Db::name('user_account')->where('user_id', $userId)
            ->update(['withdraw_status' => 'frozen']);
    }

    /**
     * 增加用户风险分（用于后续分析）
     */
    private function increaseRiskScore($userId, $points)
    {
        Db::name('user_profile')->where('user_id', $userId)
            ->inc('risk_score', $points)
            ->update();
    }

    /**
     * 发送告警通知（可接入钉钉、微信、短信）
     */
    private function sendAlert($title, $content)
    {
        Log::alert($title, ['msg' => $content]);
        // TODO: 实际接入告警系统
    }

    /**
     * 获取标签配置（带缓存）
     */
    private function getTagConfig($tagCode)
    {
        static $cache = null;
        if ($cache === null) {
            $cache = Db::name('risk_tag')
                ->where('status', 1)
                ->column([
                    'code' => 'code',
                    'name' => 'tag_name',
                    'risk_level' => 'severity',
                    'risk_score' => 'score'
                ], 'code');
        }
        return $cache[$tagCode] ?? null;
    }
}